/*
 *  dna_device.h -- provide dna-system device layer operation interface.
 *  
 *  Provide product related process method, as follows:
 *
 *     @ Manufacturer's product communication protocol
 *     @ Device operation management (set/get)
 *     @ Special command process
 *
 *  Notice: the upper layer operating device can use standard binary mode, 
 *  It doesn't contain device protocol frame header and tail, only keep device status part,
 *  So developers need to implement data_unpack and data_pack interface used for convert 
 *  standard binary format and device private protocol.
 *
 *  Error code please refer to dna_errno.h
 *
 *  ORIGINAL AUTHOR: Xu Chun (chun.xu@broadlink.com.cn)
 *
 *  Copyright (c) 2016 Broadlink Corporation
 */

#ifndef __DNA_DEVICE_H
#define __DNA_DEVICE_H

#include "dna_devicecmd.h"

#ifdef __cplusplus
    extern "C" {
#endif

/* dna-system now support device ID list */
typedef enum {
    DNA_DEVICE_BROADLINK             =  0,
    DNA_DEVICE_GALANZ,
    DNA_DEVICE_MIDEA,
    DNA_DEVICE_SUPOR,
    DNA_DEVICE_GIZWITS,
    DNA_DEVICE_HONGYAN,
} dna_device_id_e;

/* dna-system device frame type code */
typedef enum {
    DNA_DEVICE_FRAME_STATUS          =  0,
    DNA_DEVICE_FRAME_CONTROL,
} dna_device_frame_type_e;

/* dna-system device frame capture type */
typedef enum {
    DNA_DEVICE_CAPTURE_SPECIAL_CMD   =  0,
    DNA_DEVICE_CAPTURE_USER_RCV_FRAME,
    DNA_DEVICE_CAPTURE_ORPHAN_FRAME,
} dna_device_capture_type_e;

/* dna-system device uplink special command data descriptor.
*  @data: special command data structure
*  @len: data length or maxsize
*/
typedef struct dna_device_uplink_data {
    void * data;
    unsigned int len;
} dna_device_uplink_data_t;

/* dna-system device downlink special command data descriptor.
*  @data: special command data structure
*  @len: data length or maxsize
*/
typedef struct dna_device_downlink_data {
    void * data;
    unsigned int len;
} dna_device_downlink_data_t;

/* dna-system device event handler callback interface */
typedef struct dna_device_event_handler {
    /* Pre-handle: output application layer process result based on command type and
      *  Input data.
      *
      *   @type: uplink special command type code, refer to dna_device_uplink_cmd_e
      *   @input: uplink data, refer to special command data structure
      *   @output: downlink data, refer to special command data structure
      *
      *   Return 0 on success.
      */
    int (* pre_handle)(
                unsigned int type,
                dna_device_uplink_data_t * input,
                dna_device_downlink_data_t * output
    );
    /* 
      *  Post-handle: such as reset command, will cause system reboot.
      *
      *  @type: uplink special command type code, refer to dna_device_uplink_cmd_e
      *
      *  Return 0 on success.
      */
    int (* post_handle)(unsigned int type);
} dna_device_event_handler_t;

/* dna-system device basic attributes */
typedef struct dna_device_base_attr {
	/* Send request to device max retry count */
	unsigned int num_retry;
	/* Send request to device max wait response time (ms) */
	unsigned int wait_time;
	/* Send request to device interval time (ms) */
	unsigned int send_interval;
} dna_device_base_attr_t;

/*
*  dna-system device handler callback interface list,
*  This callback can help us to mask product features, so all device 
*  Seem to be unified. they implemented by product developers,
*  Then register them to device SDK.
*
*  Notice: this callback interface must non-blocking (simple and efficient).
*/
typedef struct dna_device_handler {
	/* Device initialize and uninitialize */
	int (* init)(void * arg);
	int (* deinit)(void * arg);
    /* 
	*  Device hardware interface (such as UART/SPI/I2C) write callback method.
	*  Return actual written number.
	*
	*  Notice: non-blocking.
	*/
    int (* write)(void * arg, const unsigned char * buff, unsigned int len);
    /* 
	*  Device hardware interface (such as UART/SPI/I2C) read callback method.
	*  Return actual read number.
	*
	*  Notice: non-blocking.
	*/
    int (* read)(void * arg, unsigned char * buff, unsigned int len);
	/*
      *  More than one frame together, so this callback must can split them, and 
      *  Return the first valid frame.
      *  
      *  @offset: the first valid frame start position
      * 
      *  Return frame valid length, if return <=0 means frame can't identify.
      */
	int (* frame_split)(
	            void * arg,
	            const unsigned char * input, unsigned int len,
	            unsigned int * offset
	);
	/*
      *  Special command uplink process (Device -> WiFi module), if command match success, 
      *  Then return command type (>=0, refer to dna_device_uplink_cmd_e).
      *
      *  @output: uplink data, refer to special command data structure,
      *  It will be passed to APP layer event pre-handle interface.
      */
	int (* special_cmd_uplink)(
	            void * arg,
	            const unsigned char * input, unsigned int len,
	            dna_device_uplink_data_t * output
	);
    /*
      *  Special command downlink process (WiFi module -> Device), output downlink data frame 
      *  According to the command type (refer to dna_device_downlink_cmd_e).
	*
	*  @input: downlink data, refer to special command data structure,
	*  It used for help device handler generate command frame.
	*
	*  Return output frame valid length.
	*/
	int (* special_cmd_downlink)(
	            void * arg,
	            unsigned int type, dna_device_downlink_data_t * input,
				unsigned char * output, unsigned int maxsize
	);
	/*
	*  Add frame header and tail.
	*
	*  @type: packet type (0 - status, 1 - control, refer to dna_device_frame_type_e)
	*  @input: standard binary
	*  @output: device private protocol frame
	*
	*  Return output frame valid length.
	*/
	int (* data_pack)(
	            void * arg,
	            unsigned int type,
				const unsigned char * input, unsigned int len,
				unsigned char * output, unsigned int maxsize
	);
	/*
	*  Delete frame header and tail.
	*  (Only used for device status query response packet or device active upload status packet,
	*   Notice the data section <exclude header> of the two packages must be the same)
      *
      *  @input: device private protocol frame
      *  @output: standard binary
      *
      *  Return output frame valid length.
      */
	int (* data_unpack)(
	            void * arg,
				const unsigned char * input, unsigned int len,
				unsigned char * output, unsigned int maxsize
	);
} dna_device_handler_t;

/* dna-system device frame capture callback routine (registed by user) */
typedef void (* dna_device_capture_cb_t)(
    int type,
    const unsigned char * frame, int len,
    void * arg);

/*
*  dna-system device data passthrough interface.
*
*  @input : input data (device protocol data)
*  @len  : input data valid length
*  @output: output buffer (device protocol data)
*  @maxsize : output buffer max size
*
*  Notice: if output or maxsize not specified, then interface only send, it don't wait for device response,
*  Return 0 immediately when send done. wait device response will cause sleep, so user don't call it 
*  In interrupt context.
*
*  Return output valid length, if return <=0 means device no response or occurred error.
*/
int dna_device_passthrough(
        const unsigned char * input, unsigned int len,
        unsigned char * output, unsigned int maxsize);

/*
*  dna-system device control interface,
*  This interface will call data_pack and data_unpack.
*
*  @input : input data (standard binary)
*  @len  : input data valid length
*  @output: output buffer (standard binary)
*  @maxsize : output buffer max size
*
*  Notice: if output or maxsize not specified, then interface only send, it don't wait for device response,
*  Return 0 immediately when send done. wait device response will cause sleep, so user don't call it 
*  In interrupt context.
*
*  Return output valid length, if return <=0 means device no response or occurred error.
*/
int dna_device_control(
        const unsigned char * input, unsigned int len,
        unsigned char * output, unsigned int maxsize);

/*
*  dna-system get device status interface,
*  This interface will call data_unpack.
*
*  @output: output buffer (standard binary)
*  @maxsize : output buffer max size
*
*  Notice: it is a synchronous operation interface, will cause sleep,
*  So user don't call it in interrupt context.
*
*  Return output valid length, if return <=0 means device occurred error.
*/
int dna_device_status(unsigned char * output, unsigned int maxsize);

/*
*  dna-system device event handler callback interface register.
*  It used for notice the application layer to process when received uplink special command.
*
*  @handle: device event handler interface
*
*  Return 0 means event handler interface register success.
*/
int dna_device_event_handler_register(
        dna_device_event_handler_t * handle);

/*
*  dna-system device downlink special command send interface.
*
*  @type: downlink special command type code (such as network state notice command),
*  Please refer to dna_device_downlink_cmd_e.
*  @input: downlink data, used for help device handler generate command frame
*  @output: output buffer (store device response)
*  @maxsize : output buffer max size
*
*  Return 0 means special command send success, if return <0 means occurred error.
*/
int dna_device_special_cmd_send(
        unsigned int type, dna_device_downlink_data_t * input,
        unsigned char * output, unsigned int maxsize);

/*
*  dna-system device frame capture interface (used for DEBUG on APP layer).
*
*  @filter: capture filter, please refer to dna_device_capture_type_e
*  @callback: capture callback routine, it registed by user
*  @arg: user parameters (optional)
*/
int dna_device_capture(
        int filter,
        dna_device_capture_cb_t callback, void * arg);

/*
*  dna-system device hardware communication interface param reconfigure.
*
*  @attr: device basic attributes
*
*  Return 0 means param reconfigure success.
*/
int dna_device_interf_reconfig(dna_device_base_attr_t * attr);

/*
*  dna-system device dynamic register interface.
*
*  @handle: device handler (please refer to dna_device_handler_t)
*
*  Return device unique ID (> 0) means register success, if return <0 means register error.
*/
int dna_device_register(dna_device_handler_t * handle);

/*
*  dna-system device dynamic unregister interface.
*
*  @devid: device unique ID
*
*  Return 0 means unregister success, if return <0 means unregister error.
*/
int dna_device_unregister(unsigned int devid);

/*
*  dna-system device initialization.
*
*  @devid: device unique ID
*  @attr: device basic attributes
*  @event_handle: device event handler interface (optional)
*  @arg: user parameters (optional)
*
*  Return 0 means initialize success, if return <0 means occurred error.
*/
int dna_device_init(
        unsigned int devid,
        dna_device_base_attr_t * attr,
        dna_device_event_handler_t * event_handle,
        void * arg);

/*
*  dna-system device uninitialize.
*
*  Return 0 means uninitialize success, if return <0 means occurred error.
*/
int dna_device_deinit(void);

#ifdef __cplusplus
}
#endif

#endif

